<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
    "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
<meta name="generator" content="AsciiDoc 8.6.3" />
<title>Gerrit Code Review - Hooks</title>
<style type="text/css">
/* Sans-serif font. */
h1, h2, h3, h4, h5, h6,
div.title, caption.title,
thead, p.table.header,
div#toctitle,
span#author, span#revnumber, span#revdate, span#revremark,
div#footer {
  font-family: Arial,Helvetica,sans-serif;
}

/* Serif font. */
div.sectionbody {
  font-family: Georgia,"Times New Roman",Times,serif;
}

/* Monospace font. */
tt {
  font-size: inherit;
}

body {
  margin: 1em 5% 1em 5%;
}

a {
  color: blue;
  text-decoration: underline;
}
a:visited {
  color: fuchsia;
}

em {
  font-style: italic;
  color: navy;
}

strong {
  font-weight: bold;
  color: #083194;
}

tt {
  font-size: inherit;
  color: navy;
}

h1, h2, h3, h4, h5, h6 {
  color: #527bbd;
  margin-top: 1.2em;
  margin-bottom: 0.5em;
  line-height: 1.3;
}

h1, h2, h3 {
  border-bottom: 2px solid silver;
}
h2 {
  padding-top: 0.5em;
}
h3 {
  float: left;
}
h3 + * {
  clear: left;
}

div.sectionbody {
  margin-left: 0;
}

hr {
  border: 1px solid silver;
}

p {
  margin-top: 0.5em;
  margin-bottom: 0.5em;
}

ul, ol, li > p {
  margin-top: 0;
}
ul > li     { color: #aaa; }
ul > li > * { color: black; }

pre {
  padding: 0;
  margin: 0;
}

span#author {
  color: #527bbd;
  font-weight: bold;
  font-size: 1.1em;
}
span#email {
}
span#revnumber, span#revdate, span#revremark {
}

div#footer {
  font-size: small;
  border-top: 2px solid silver;
  padding-top: 0.5em;
  margin-top: 4.0em;
}
div#footer-text {
  float: left;
  padding-bottom: 0.5em;
}
div#footer-badges {
  float: right;
  padding-bottom: 0.5em;
}

div#preamble {
  margin-top: 1.5em;
  margin-bottom: 1.5em;
}
div.tableblock, div.imageblock, div.exampleblock, div.verseblock,
div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,
div.admonitionblock {
  margin-top: 1.0em;
  margin-bottom: 1.5em;
}
div.admonitionblock {
  margin-top: 2.0em;
  margin-bottom: 2.0em;
  margin-right: 10%;
  color: #606060;
}

div.content { /* Block element content. */
  padding: 0;
}

/* Block element titles. */
div.title, caption.title {
  color: #527bbd;
  font-weight: bold;
  text-align: left;
  margin-top: 1.0em;
  margin-bottom: 0.5em;
}
div.title + * {
  margin-top: 0;
}

td div.title:first-child {
  margin-top: 0.0em;
}
div.content div.title:first-child {
  margin-top: 0.0em;
}
div.content + div.title {
  margin-top: 0.0em;
}

div.sidebarblock > div.content {
  background: #ffffee;
  border: 1px solid #dddddd;
  border-left: 4px solid #f0f0f0;
  padding: 0.5em;
}

div.listingblock > div.content {
  border: 1px solid #dddddd;
  border-left: 5px solid #f0f0f0;
  background: #f8f8f8;
  padding: 0.5em;
}

div.quoteblock, div.verseblock {
  padding-left: 1.0em;
  margin-left: 1.0em;
  margin-right: 10%;
  border-left: 5px solid #f0f0f0;
  color: #777777;
}

div.quoteblock > div.attribution {
  padding-top: 0.5em;
  text-align: right;
}

div.verseblock > pre.content {
  font-family: inherit;
  font-size: inherit;
}
div.verseblock > div.attribution {
  padding-top: 0.75em;
  text-align: left;
}
/* DEPRECATED: Pre version 8.2.7 verse style literal block. */
div.verseblock + div.attribution {
  text-align: left;
}

div.admonitionblock .icon {
  vertical-align: top;
  font-size: 1.1em;
  font-weight: bold;
  text-decoration: underline;
  color: #527bbd;
  padding-right: 0.5em;
}
div.admonitionblock td.content {
  padding-left: 0.5em;
  border-left: 3px solid #dddddd;
}

div.exampleblock > div.content {
  border-left: 3px solid #dddddd;
  padding-left: 0.5em;
}

div.imageblock div.content { padding-left: 0; }
span.image img { border-style: none; }
a.image:visited { color: white; }

dl {
  margin-top: 0.8em;
  margin-bottom: 0.8em;
}
dt {
  margin-top: 0.5em;
  margin-bottom: 0;
  font-style: normal;
  color: navy;
}
dd > *:first-child {
  margin-top: 0.1em;
}

ul, ol {
    list-style-position: outside;
}
ol.arabic {
  list-style-type: decimal;
}
ol.loweralpha {
  list-style-type: lower-alpha;
}
ol.upperalpha {
  list-style-type: upper-alpha;
}
ol.lowerroman {
  list-style-type: lower-roman;
}
ol.upperroman {
  list-style-type: upper-roman;
}

div.compact ul, div.compact ol,
div.compact p, div.compact p,
div.compact div, div.compact div {
  margin-top: 0.1em;
  margin-bottom: 0.1em;
}

div.tableblock > table {
  border: 3px solid #527bbd;
}
thead, p.table.header {
  font-weight: bold;
  color: #527bbd;
}
tfoot {
  font-weight: bold;
}
td > div.verse {
  white-space: pre;
}
p.table {
  margin-top: 0;
}
/* Because the table frame attribute is overriden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
  border-style: none;
}
div.tableblock > table[frame="hsides"] {
  border-left-style: none;
  border-right-style: none;
}
div.tableblock > table[frame="vsides"] {
  border-top-style: none;
  border-bottom-style: none;
}


div.hdlist {
  margin-top: 0.8em;
  margin-bottom: 0.8em;
}
div.hdlist tr {
  padding-bottom: 15px;
}
dt.hdlist1.strong, td.hdlist1.strong {
  font-weight: bold;
}
td.hdlist1 {
  vertical-align: top;
  font-style: normal;
  padding-right: 0.8em;
  color: navy;
}
td.hdlist2 {
  vertical-align: top;
}
div.hdlist.compact tr {
  margin: 0;
  padding-bottom: 0;
}

.comment {
  background: yellow;
}

.footnote, .footnoteref {
  font-size: 0.8em;
}

span.footnote, span.footnoteref {
  vertical-align: super;
}

#footnotes {
  margin: 20px 0 20px 0;
  padding: 7px 0 0 0;
}

#footnotes div.footnote {
  margin: 0 0 5px 0;
}

#footnotes hr {
  border: none;
  border-top: 1px solid silver;
  height: 1px;
  text-align: left;
  margin-left: 0;
  width: 20%;
  min-width: 100px;
}

div.colist td {
  padding-right: 0.5em;
  padding-bottom: 0.3em;
  vertical-align: top;
}
div.colist td img {
  margin-top: 0.3em;
}

@media print {
  div#footer-badges { display: none; }
}

div#toc {
  margin-bottom: 2.5em;
}

div#toctitle {
  color: #527bbd;
  font-size: 1.1em;
  font-weight: bold;
  margin-top: 1.0em;
  margin-bottom: 0.1em;
}

div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 {
  margin-top: 0;
  margin-bottom: 0;
}
div.toclevel2 {
  margin-left: 2em;
  font-size: 0.9em;
}
div.toclevel3 {
  margin-left: 4em;
  font-size: 0.9em;
}
div.toclevel4 {
  margin-left: 6em;
  font-size: 0.9em;
}

</style>
<script type="text/javascript">
/*<![CDATA[*/
window.onload = function(){asciidoc.footnotes(); asciidoc.toc(2);}
var asciidoc = {  // Namespace.

/////////////////////////////////////////////////////////////////////
// Table Of Contents generator
/////////////////////////////////////////////////////////////////////

/* Author: Mihai Bazon, September 2002
 * http://students.infoiasi.ro/~mishoo
 *
 * Table Of Content generator
 * Version: 0.4
 *
 * Feel free to use this script under the terms of the GNU General Public
 * License, as long as you do not remove or alter this notice.
 */

 /* modified by Troy D. Hanson, September 2006. License: GPL */
 /* modified by Stuart Rackham, 2006, 2009. License: GPL */

// toclevels = 1..4.
toc: function (toclevels) {

  function getText(el) {
    var text = "";
    for (var i = el.firstChild; i != null; i = i.nextSibling) {
      if (i.nodeType == 3 /* Node.TEXT_NODE */) // IE doesn't speak constants.
        text += i.data;
      else if (i.firstChild != null)
        text += getText(i);
    }
    return text;
  }

  function TocEntry(el, text, toclevel) {
    this.element = el;
    this.text = text;
    this.toclevel = toclevel;
  }

  function tocEntries(el, toclevels) {
    var result = new Array;
    var re = new RegExp('[hH]([2-'+(toclevels+1)+'])');
    // Function that scans the DOM tree for header elements (the DOM2
    // nodeIterator API would be a better technique but not supported by all
    // browsers).
    var iterate = function (el) {
      for (var i = el.firstChild; i != null; i = i.nextSibling) {
        if (i.nodeType == 1 /* Node.ELEMENT_NODE */) {
          var mo = re.exec(i.tagName);
          if (mo && (i.getAttribute("class") || i.getAttribute("className")) != "float") {
            result[result.length] = new TocEntry(i, getText(i), mo[1]-1);
          }
          iterate(i);
        }
      }
    }
    iterate(el);
    return result;
  }

  var toc = document.getElementById("toc");
  var entries = tocEntries(document.getElementById("content"), toclevels);
  for (var i = 0; i < entries.length; ++i) {
    var entry = entries[i];
    if (entry.element.id == "")
      entry.element.id = "_toc_" + i;
    var a = document.createElement("a");
    a.href = "#" + entry.element.id;
    a.appendChild(document.createTextNode(entry.text));
    var div = document.createElement("div");
    div.appendChild(a);
    div.className = "toclevel" + entry.toclevel;
    toc.appendChild(div);
  }
  if (entries.length == 0)
    toc.parentNode.removeChild(toc);
},


/////////////////////////////////////////////////////////////////////
// Footnotes generator
/////////////////////////////////////////////////////////////////////

/* Based on footnote generation code from:
 * http://www.brandspankingnew.net/archive/2005/07/format_footnote.html
 */

footnotes: function () {
  var cont = document.getElementById("content");
  var noteholder = document.getElementById("footnotes");
  var spans = cont.getElementsByTagName("span");
  var refs = {};
  var n = 0;
  for (i=0; i<spans.length; i++) {
    if (spans[i].className == "footnote") {
      n++;
      // Use [\s\S] in place of . so multi-line matches work.
      // Because JavaScript has no s (dotall) regex flag.
      note = spans[i].innerHTML.match(/\s*\[([\s\S]*)]\s*/)[1];
      noteholder.innerHTML +=
        "<div class='footnote' id='_footnote_" + n + "'>" +
        "<a href='#_footnoteref_" + n + "' title='Return to text'>" +
        n + "</a>. " + note + "</div>";
      spans[i].innerHTML =
        "[<a id='_footnoteref_" + n + "' href='#_footnote_" + n +
        "' title='View footnote' class='footnote'>" + n + "</a>]";
      var id =spans[i].getAttribute("id");
      if (id != null) refs["#"+id] = n;
    }
  }
  if (n == 0)
    noteholder.parentNode.removeChild(noteholder);
  else {
    // Process footnoterefs.
    for (i=0; i<spans.length; i++) {
      if (spans[i].className == "footnoteref") {
        var href = spans[i].getElementsByTagName("a")[0].getAttribute("href");
        href = href.match(/#.*/)[0];  // Because IE return full URL.
        n = refs[href];
        spans[i].innerHTML =
          "[<a href='#_footnote_" + n +
          "' title='View footnote' class='footnote'>" + n + "</a>]";
      }
    }
  }
}

}
/*]]>*/
</script>
</head>
<body class="article">
<div id="header">
<h1>Gerrit Code Review - Hooks</h1>
<span id="revnumber">version 2.5</span>
<div id="toc">
  <div id="toctitle">Table of Contents</div>
  <noscript><p><b>JavaScript must be enabled in your browser to display the table of contents.</b></p></noscript>
</div>
</div>
<div id="content">
<div id="preamble">
<div class="sectionbody">
<div class="paragraph"><p>Gerrit does not run any of the standard git hooks in the
repositories it works with, but it does have its own hook mechanism
included. Gerrit looks in <tt>'$site_path'/hooks</tt> for executables with
names listed below.</p></div>
<div class="paragraph"><p>The environment will have GIT_DIR set to the full path of the
affected git repository so that git commands can be easily run.</p></div>
<div class="paragraph"><p>Make sure your hook scripts are executable if running on *nix.</p></div>
<div class="paragraph"><p>Hooks are run in the background after the relevant change has
taken place so are unable to affect the outcome of any given
change. Because of the fact the hooks are run in the background
after the activity, a hook might not be notified about an event if
the server is shutdown before the hook can be invoked.</p></div>
</div>
</div>
<div class="sect1">
<h2 id="_supported_hooks">Supported Hooks</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="_patchset_created">patchset-created</h3>
<div class="paragraph"><p>This is called whenever a patchset is created (this includes new
changes and drafts).</p></div>
<div class="exampleblock">
<div class="content">
<div class="literalblock">
<div class="content">
<pre><tt>patchset-created --change &lt;change id&gt; --is-draft &lt;boolean&gt; --change-url &lt;change url&gt; --project &lt;project name&gt; --branch &lt;branch&gt; --topic &lt;topic&gt; --uploader &lt;uploader&gt; --commit &lt;sha1&gt; --patchset &lt;patchset id&gt;</tt></pre>
</div></div>
</div></div>
</div>
<div class="sect2">
<h3 id="_draft_published">draft-published</h3>
<div class="paragraph"><p>This is called whenever a draft change is published.</p></div>
<div class="exampleblock">
<div class="content">
<div class="literalblock">
<div class="content">
<pre><tt>draft-published --change &lt;change id&gt; --change-url &lt;change url&gt; --project &lt;project name&gt; --branch &lt;branch&gt; --topic &lt;topic&gt; --uploader &lt;uploader&gt; --commit &lt;sha1&gt; --patchset &lt;patchset id&gt;</tt></pre>
</div></div>
</div></div>
</div>
<div class="sect2">
<h3 id="_comment_added">comment-added</h3>
<div class="paragraph"><p>This is called whenever a comment is added to a change.</p></div>
<div class="exampleblock">
<div class="content">
<div class="literalblock">
<div class="content">
<pre><tt>comment-added --change &lt;change id&gt; --change-url &lt;change url&gt; --project &lt;project name&gt; --branch &lt;branch&gt; --topic &lt;topic&gt; --author &lt;comment author&gt; --commit &lt;commit&gt; --comment &lt;comment&gt; [--&lt;approval category id&gt; &lt;score&gt; --&lt;approval category id&gt; &lt;score&gt; ...]</tt></pre>
</div></div>
</div></div>
</div>
<div class="sect2">
<h3 id="_change_merged">change-merged</h3>
<div class="paragraph"><p>Called whenever a change has been merged.</p></div>
<div class="exampleblock">
<div class="content">
<div class="literalblock">
<div class="content">
<pre><tt>change-merged --change &lt;change id&gt; --change-url &lt;change url&gt; --project &lt;project name&gt; --branch &lt;branch&gt; --topic &lt;topic&gt; --submitter &lt;submitter&gt; --commit &lt;sha1&gt;</tt></pre>
</div></div>
</div></div>
</div>
<div class="sect2">
<h3 id="_change_abandoned">change-abandoned</h3>
<div class="paragraph"><p>Called whenever a change has been abandoned.</p></div>
<div class="exampleblock">
<div class="content">
<div class="literalblock">
<div class="content">
<pre><tt>change-abandoned --change &lt;change id&gt; --change-url &lt;change url&gt; --project &lt;project name&gt; --branch &lt;branch&gt; --topic &lt;topic&gt; --abandoner &lt;abandoner&gt; --reason &lt;reason&gt;</tt></pre>
</div></div>
</div></div>
</div>
<div class="sect2">
<h3 id="_change_restored">change-restored</h3>
<div class="paragraph"><p>Called whenever a change has been restored.</p></div>
<div class="exampleblock">
<div class="content">
<div class="literalblock">
<div class="content">
<pre><tt>change-restored --change &lt;change id&gt; --change-url &lt;change url&gt; --project &lt;project name&gt; --branch &lt;branch&gt; --topic &lt;topic&gt; --restorer &lt;restorer&gt; --reason &lt;reason&gt;</tt></pre>
</div></div>
</div></div>
</div>
<div class="sect2">
<h3 id="_ref_updated">ref-updated</h3>
<div class="paragraph"><p>Called whenever a ref has been updated.</p></div>
<div class="exampleblock">
<div class="content">
<div class="literalblock">
<div class="content">
<pre><tt>ref-updated --oldrev &lt;old rev&gt; --newrev &lt;new rev&gt; --refname &lt;ref name&gt; --project &lt;project name&gt; --submitter &lt;submitter&gt;</tt></pre>
</div></div>
</div></div>
</div>
<div class="sect2">
<h3 id="_cla_signed">cla-signed</h3>
<div class="paragraph"><p>Called whenever a user signs a contributor license agreement.</p></div>
<div class="exampleblock">
<div class="content">
<div class="literalblock">
<div class="content">
<pre><tt>cla-signed --submitter &lt;submitter&gt; --user-id &lt;user_id&gt; --cla-id &lt;cla_id&gt;</tt></pre>
</div></div>
</div></div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_configuration_settings">Configuration Settings</h2>
<div class="sectionbody">
<div class="paragraph"><p>It is possible to change where Gerrit looks for hooks, and what
filenames it looks for, by adding a [hooks] section in gerrit.config.</p></div>
<div class="paragraph"><p>Gerrit will use the value of hooks.path for the hooks directory.</p></div>
<div class="paragraph"><p>For the hook filenames, Gerrit will use the values of hooks.patchsetCreatedHook,
hooks.draftPublishedHook, hooks.commentAddedHook, hooks.changeMergedHook,
hooks.changeAbandonedHook, hooks.changeRestoredHook, hooks.refUpdatedHook and
hooks.claSignedHook.</p></div>
</div>
</div>
<div class="sect1">
<h2 id="_missing_change_urls">Missing Change URLs</h2>
<div class="sectionbody">
<div class="paragraph"><p>If <a href="config-gerrit.html#gerrit.canonicalWebUrl">gerrit.canonicalWebUrl</a>
is not set in <tt>gerrit.config</tt> the <tt>--change-url</tt> flag may not be
passed to all hooks.  Hooks started out of an SSH context (for example
the patchset-created hook) don&#8217;t know the server&#8217;s web URL, unless
this variable is configured.</p></div>
</div>
</div>
<div class="sect1">
<h2 id="_see_also">See Also</h2>
<div class="sectionbody">
<div class="ulist"><ul>
<li>
<p>
<a href="config-gerrit.html#hooks">Section hooks</a>
</p>
</li>
</ul></div>
</div>
</div>
<hr style="
  height: 2px;
  color: silver;
  margin-top: 1.2em;
  margin-bottom: 0.5em;
">
<div class="paragraph"><p>Part of <a href="index.html">Gerrit Code Review</a></p></div>
</div>
<div id="footnotes"><hr /></div>
<div id="footer">
<div id="footer-text">
Version 2.5<br />
Last updated 2012-10-31 19:34:02 CET
</div>
</div>
</body>
</html>
